﻿using System;
using System.Linq;
using c = NHibernate.Cfg;

namespace OrmSmackdown.LinqToNHibernate
{
    public class Aggregate : IAggregate
    {
        OrmSmackdownContext _ctx;

        public Aggregate()
        {
            c.Configuration _configuration = new c.Configuration();
            _configuration.AddAssembly("OrmSmackdown");
            var sessionFactory = _configuration.BuildSessionFactory();
            var session = sessionFactory.OpenSession();
            _ctx = new OrmSmackdownContext(session);
        }

        public void InsertRecordsApproachOne(int recordsToInsert)
        {
            using(var transaction = _ctx.Session.BeginTransaction())
            {
                for (var idx = 0; idx < recordsToInsert; ++idx)
                {
                    var perf = new NHibernate.Performance() { MilliSeconds = idx, Action = Constants.STR_AggregateCount, OrmName = "Linq2NHibernate" };
                    _ctx.Session.Save(perf);
                }
                transaction.Commit();
            }
        }

        public void InsertRecordsApproachTwo(int recordsToInsert)
        {
            for (var idx = 0; idx < recordsToInsert; ++idx)
            {
                var perf = new NHibernate.Performance() { MilliSeconds = idx, Action = Constants.STR_AggregateCount, OrmName = "Linq2NHibernate" };
                _ctx.Session.Save(perf);
            }

            _ctx.Session.Flush();
        }

        public int GetCountApproachOne()
        {
            return _ctx.Performance.Count(prf => prf.Action == Constants.STR_AggregateCount);
        }

        public int GetCountApproachTwo()
        {
            var query = from perf
                        in _ctx.Performance
                        where perf.Action == Constants.STR_AggregateCount
                        select perf.MilliSeconds;

            //Will load and return the complete list to the client.  Then the count will be displayed as the count of the list.
            return query.ToList().Count;
        }

        public int GetAverageApproachOne()
        {
            return Convert.ToInt32(_ctx.Performance.Where(perf=>perf.Action == Constants.STR_AggregateCount).Average(prf=>prf.MilliSeconds));
        }

        public int GetAverageApproachTwo()
        {
            var query = from perf
                        in _ctx.Performance
                        where perf.Action == Constants.STR_AggregateCount
                        select perf.MilliSeconds;

            return Convert.ToInt32(query.Average());
        }      

        public void DeleteRecordsApproachOne()
        {
            AdoNet.Aggregate.ClearAggregateCounts();
        }

        public void DeleteRecordsApproachTwo()
        {
            AdoNet.Aggregate.ClearAggregateCounts();
        }

        public void Dispose()
        {
            _ctx.Dispose();
        }
    }
}
